package com.example.common.utils;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * @createTime 2020/8/25 15:07
 * @description 视频帧处理工具
 */
public class VideoFrameUtil  {

    private static final Logger logger = LoggerFactory.getLogger(VideoFrameUtil.class);


    /**
     * @author charles
     * @createTime 2020/8/26 10:18
     * @desc 通过视频流  获取视频的第一帧
     */
    public static InputStream grabberVideoFramer(InputStream inputStream) throws IOException{
        FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(inputStream);
        return grabberVideoFramer(fFmpegFrameGrabber);
    }


    /**
     * @author charles
     * @createTime 2020/8/27 9:14
     * @desc 获取视频时长
     */
    public static double videoTimeLength(FFmpegFrameGrabber fFmpegFrameGrabber){
        int ftp = fFmpegFrameGrabber.getLengthInFrames();
        return ftp / fFmpegFrameGrabber.getFrameRate();
    }


    /**
     * @author charles
     * @createTime 2020/8/26 10:19
     * @desc 获取视频的第一帧
     */
    private static InputStream grabberVideoFramer(FFmpegFrameGrabber fFmpegFrameGrabber) throws IOException{
        fFmpegFrameGrabber.start();
        int ftp = fFmpegFrameGrabber.getLengthInFrames();
        if (ftp > 0){
            // 获取一帧
            Frame frame = fFmpegFrameGrabber.grabImage();
            BufferedImage bufferedImage = FrameToBufferedImage(frame);
            // 图片输出流
            InputStream inputStream = bufferedImageToInputStream(bufferedImage);
            fFmpegFrameGrabber.stop();
            return inputStream;
        }
        return null;
    }


    /**
     * @author charles
     * @createTime 2020/8/27 8:54
     * @desc 本地测试截取任意帧
     */
    public static String grabberVideoFramerLocal(String videoFileName, int frameNum,String newFile,String realpathStr) throws IOException{
        FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoFileName);
        fFmpegFrameGrabber.start();
        double length = videoTimeLength(fFmpegFrameGrabber);
        if (length < frameNum){
            logger.info("截取的视频帧不能超过视频总帧数！");
            return "";
        }
        //Frame对象
        Frame frame = null;
        String rotate_old=fFmpegFrameGrabber.getVideoMetadata("rotate");//视频旋转角度，可能是null
        // 输出视频的每一帧
        for (int i = 1; i <= length; i++) {
            //获取帧
            frame = fFmpegFrameGrabber.grabImage();
            if (i == frameNum){
                //文件绝对路径+名字
                String fileName = realpathStr + newFile + ".png";
                //文件储存对象
                File outPut = new File(fileName);
                if (frame != null) {
                    ImageIO.write(FrameToBufferedImage(frame), "png", outPut);
                }
                fFmpegFrameGrabber.stop();
                //有需要旋转
                if(rotate_old!=null && !rotate_old.isEmpty()){
                    int rotate=Integer.parseInt(rotate_old);
                    rotatePhonePhoto(fileName,rotate);
                }
                return newFile + ".png";
            }
        }
        fFmpegFrameGrabber.stop();
        return "";
    }


    /**
     * @author charles
     * @createTime 2020/8/26 10:32
     * @desc 转换对象
     */
    public static BufferedImage FrameToBufferedImage(Frame frame) {
        //创建BufferedImage对象
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        return bufferedImage;
    }


    /**
     * 将BufferedImage转换为InputStream
     * @param image
     * @return
     */
    public static InputStream bufferedImageToInputStream(BufferedImage image){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", os);
            return new ByteArrayInputStream(os.toByteArray());
        } catch (IOException e) {
            logger.error("获取视频帧失败", e);
        }
        return null;
    }

    /**
     * 旋转照片
     * @param fullPath
     * @param angel
     * @return
     */
    public static String rotatePhonePhoto(String fullPath, int angel) {
        BufferedImage src;
        try {
            src = ImageIO.read(new File(fullPath));
            int src_width = src.getWidth(null);
            int src_height = src.getHeight(null);

            int swidth = src_width;
            int sheight = src_height;

            if (angel == 90 || angel == 270) {
                swidth = src_height;
                sheight = src_width;
            }
            Rectangle rect_des = new Rectangle(new Dimension(swidth, sheight));
            BufferedImage res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = res.createGraphics();
            g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
            g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
            g2.drawImage(src, null, null);
            ImageIO.write(res,"png", new File(fullPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fullPath;

    }


    /**
     * @author charles
     * @createTime 2020/8/27 8:58
     * @desc 测试
     */
    public static void main(String[] args) throws IOException {
        // 获取视频的第一帧测试
        String videoFileName = "1586490_A.mp4";
//        InputStream inputStream = grabberVideoFramer(videoFileName);
//        String test = new SaveFileUtil().saveImg(inputStream, "test11111.png");
//        System.out.println(test);
        // 获取视频的任意帧
//        grabberVideoFramerLocal(videoFileName, 1);
    }
}